﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.IO;

namespace Kwan.Helper.Bitmaps
{
    public enum MarkType
    {
        Text, Image, None
    }

    /// <summary>
    /// 给图片添加水印得类得描述
    /// </summary>
    public class Watermark : IDisposable
    {
        #region 成员变量
        private string _WaterText = string.Empty;
        private string _WaterImagePath = string.Empty;
        private int _MarkX = 0;
        private int _MarkY = 0;
        private float _Transparency = 1;
        private string _FontFamily = "宋体";
        private Color _TextColor = Color.Black;
        private bool _TextBold = false;
        int[] sizes = new int[] { 48, 32, 16, 8, 6, 4 };
        private Image _SourceImage = null;
        private Image _WaterImage = null;
        private MarkType _WaterType = MarkType.Text;
        private WaterPoint _WaterPoint;
        #endregion

        #region 公共属性
        /// <summary>
        /// 水印类型
        /// </summary>
        public MarkType WaterType
        {
            get { return _WaterType; }
            set { _WaterType = value; }
        }
        /// <summary>
        /// 文字水印得内容
        /// </summary>
        public string WaterText
        {
            get { return _WaterText; }
            set { _WaterText = value; }
        }
        /// <summary>
        /// 水印图片得路径
        /// </summary>
        public string WaterImagePath
        {
            get { return _WaterImagePath; }
            set { this._WaterImagePath = value; }
        }
        /// <summary>
        /// 水印图片
        /// </summary>
        public Image WaterImage
        {
            get
            {
                try
                {
                    return Image.FromFile(this.WaterImagePath);
                }
                catch
                {
                    return null;
                }
            }
        }
        /// <summary>
        /// 添加水印位置得横坐标
        /// </summary>
        public int MarkX
        {
            get { return _MarkX; }
            set { _MarkX = value; }
        }
        /// <summary>
        /// 添加水印位置得纵坐标
        /// </summary>
        public int MarkY
        {
            get { return _MarkY; }
            set { _MarkY = value; }
        }
        /// <summary>
        /// 水印得透明度
        /// </summary>
        public float Transparency
        {
            get
            {
                if (_Transparency > 1.0f)
                {
                    _Transparency = 1.0f;
                }
                return _Transparency;
            }
            set { _Transparency = value; }
        }
        /// <summary>
        /// 水印文字得颜色
        /// </summary>
        public Color TextColor
        {
            get { return _TextColor; }
            set { _TextColor = value; }
        }
        /// <summary>
        /// 水印文字得字体
        /// </summary>
        public string FontFamily
        {
            get { return _FontFamily; }
            set { _FontFamily = value; }
        }
        /// <summary>
        /// 水印文字是否加粗
        /// </summary>
        public bool TextBold
        {
            get { return _TextBold; }
            set { _TextBold = value; }
        }
        /// <summary>
        /// 原图
        /// </summary>
        public Image SourceImage
        {
            get { return _SourceImage; }
            set { _SourceImage = value; }
        }
        /// <summary>
        /// 加过水印之后得图
        /// </summary>
        public Image MarkedImage
        {
            get { return this._WaterImage; }
        }
        /// <summary>
        /// 水印位置
        /// </summary>
        public WaterPoint WaterPoint
        {
            get { return _WaterPoint; }
            set { _WaterPoint = value; }
        }
        #endregion

        #region 构造函数
        /// <summary>
        /// 实例化一个水印类
        /// </summary>
        public Watermark()
        {

        }
        /// <summary>
        ///　初始化一个只添加文字水印得实例
        /// </summary>
        /// <param name="text">水印文字</param>
        /// <param name="fontFamily">文字字体</param>
        /// <param name="bold">是否粗体</param>
        /// <param name="color">字体颜色</param>
        /// <param name="markX">标记位置横坐标</param>
        /// <param name="markY">标记位置纵坐标</param>
        public Watermark(string text, string fontFamily, bool bold, Color color, WaterPoint point)
        {
            this._WaterType = MarkType.Text;
            this._WaterText = text;
            this._FontFamily = fontFamily;
            this._TextBold = bold;
            this._TextColor = color;
            this._WaterPoint = point;
            //this.Mark();
        }
        /// <summary>
        /// 实例化一个只添加图片水印得实例
        /// </summary>
        /// <param name="imagePath">水印图片路径</param>
        /// <param name="tranparence">透明度</param>
        /// <param name="markX">标记位置横坐标</param>
        /// <param name="markY">标记位置纵坐标</param>
        public Watermark(string imagePath, float tranparence, WaterPoint point)
        {
            this._WaterType = MarkType.Image;
            this._WaterImagePath = imagePath;
            this._Transparency = tranparence;
            this._WaterPoint = point;
            //this.Mark();
        }
        #endregion

        #region 方法事件
        public Image Mark(Image img)
        {
            try
            {
                //添加文字水印
                if (_WaterType == MarkType.Text)
                {
                    //根据源图片生成新的Bitmap对象作为作图区，为了给gif图片添加水印，才有此周折
                    Bitmap newBitmap = new Bitmap(img.Width, img.Height, PixelFormat.Format24bppRgb);
                    //设置新建位图得分辨率
                    newBitmap.SetResolution(img.HorizontalResolution, img.VerticalResolution);
                    //创建Graphics对象，以对该位图进行操作
                    Graphics g = Graphics.FromImage(newBitmap);
                    //文字区域大小
                    SizeF fontSize = g.MeasureString(_WaterText, new System.Drawing.Font(_FontFamily, 26));
                    switch (_WaterPoint.Type)
                    {
                        case WaterPoint.PointType.LeftTop:
                        default:
                            _MarkX = _WaterPoint.x;
                            _MarkY = _WaterPoint.y;
                            break;
                        case WaterPoint.PointType.LeftBottom:
                            _MarkX = _WaterPoint.x;
                            _MarkY = img.Height - _WaterPoint.y - (int)fontSize.Height;
                            break;
                        case WaterPoint.PointType.RightTop:
                            _MarkX = img.Width - _WaterPoint.x - (int)fontSize.Width;
                            _MarkY = _WaterPoint.y;
                            break;
                        case WaterPoint.PointType.RightBottom:
                            _MarkX = img.Width - _WaterPoint.x - (int)fontSize.Width;
                            _MarkY = img.Height - _WaterPoint.y - (int)fontSize.Height;
                            break;
                    }
                    if (_MarkX < 0)
                        _MarkX = 0;
                    if (_MarkY < 0)
                        _MarkY = 0;
                    //消除锯齿
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    //将原图拷贝到作图区
                    g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
                    //声明字体对象
                    Font cFont = null;
                    //用来测试水印文本长度得尺子
                    SizeF size = new SizeF();
                    //探测出一个适合图片大小得字体大小，以适应水印文字大小得自适应
                    for (int i = 0; i < 6; i++)
                    {
                        //创建一个字体对象
                        cFont = new Font(_FontFamily, sizes[i]);
                        //是否加粗
                        if (!_TextBold)
                        {
                            cFont = new Font(_FontFamily, sizes[i], FontStyle.Regular);
                        }
                        else
                        {
                            cFont = new Font(_FontFamily, sizes[i], FontStyle.Bold);
                        }
                        //测量文本大小
                        size = g.MeasureString(this.WaterText, cFont);
                        //匹配第一个符合要求得字体大小
                        if ((ushort)size.Width < (ushort)img.Width)
                        {
                            break;
                        }
                    }
                    //创建刷子对象，准备给图片写上文字
                    Brush brush = new SolidBrush(_TextColor);
                    //在指定得位置写上文字
                    g.DrawString(_WaterText, cFont, brush, _MarkX, _MarkY);
                    //释放Graphics对象
                    g.Dispose();
                    //将生成得图片读入MemoryStream
                    System.IO.MemoryStream ms = new System.IO.MemoryStream();
                    newBitmap.Save(ms, ImageFormat.Jpeg);
                    //重新生成Image对象
                    img = System.Drawing.Image.FromStream(ms);
                    //释放相关对象
                    brush.Dispose();
                    newBitmap.Dispose();
                    //返回新的Image对象
                    return img;

                }
                //添加图像水印
                else if (_WaterType == MarkType.Image)
                {
                    //获得水印图像
                    Image markImg = WaterImage;
                    //找不到水印图片直接返回原图
                    if (markImg == null) return img;
                    //设置水印图片位置
                    if (_MarkX == 0 && _MarkY == 0)
                    {
                        switch (_WaterPoint.Type)
                        {
                            case WaterPoint.PointType.LeftTop:
                            default:
                                _MarkX = _WaterPoint.x;
                                _MarkY = _WaterPoint.y;
                                break;
                            case WaterPoint.PointType.LeftBottom:
                                _MarkX = _WaterPoint.x;
                                _MarkY = img.Height - _WaterPoint.y - markImg.Height;
                                break;
                            case WaterPoint.PointType.RightTop:
                                _MarkX = img.Width - _WaterPoint.x - markImg.Width;
                                _MarkY = _WaterPoint.y;
                                break;
                            case WaterPoint.PointType.RightBottom:
                                _MarkX = img.Width - _WaterPoint.x - markImg.Width;
                                _MarkY = img.Height - _WaterPoint.y - markImg.Height;
                                break;
                        }
                        if (_MarkX < 0)
                            _MarkX = 0;
                        if (_MarkY < 0)
                            _MarkY = 0;
                    }
                    //创建颜色矩阵
                    float[][] ptsArray ={ 
                        new float[] {1, 0, 0, 0, 0},
                        new float[] {0, 1, 0, 0, 0},
                        new float[] {0, 0, 1, 0, 0},
                        new float[] {0, 0, 0, _Transparency, 0}, //注意：此处为0.0f为完全透明，1.0f为完全不透明
                        new float[] {0, 0, 0, 0, 1}
                    };
                    ColorMatrix colorMatrix = new ColorMatrix(ptsArray);
                    //新建一个Image属性
                    ImageAttributes imageAttributes = new ImageAttributes();
                    //将颜色矩阵添加到属性
                    imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default,
                        ColorAdjustType.Default);
                    //生成位图作图区
                    Bitmap newBitmap = new Bitmap(img.Width, img.Height, PixelFormat.Format24bppRgb);
                    //设置分辨率
                    newBitmap.SetResolution(img.HorizontalResolution, img.VerticalResolution);
                    //创建Graphics
                    Graphics g = Graphics.FromImage(newBitmap);
                    //消除锯齿
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    //拷贝原图到作图区
                    g.DrawImage(img, new Rectangle(0, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel);
                    //如果原图过小
                    if (markImg.Width > img.Width || markImg.Height > img.Height)
                    {
                        System.Drawing.Image.GetThumbnailImageAbort callb = null;
                        //对水印图片生成缩略图,缩小到原图得1/4
                        System.Drawing.Image new_img = markImg.GetThumbnailImage(img.Width / 4, markImg.Height * img.Width / markImg.Width, callb, new System.IntPtr());
                        //添加水印
                        g.DrawImage(new_img, new Rectangle(_MarkX, _MarkY, new_img.Width, new_img.Height), 0, 0, new_img.Width, new_img.Height, GraphicsUnit.Pixel, imageAttributes);
                        //释放缩略图
                        new_img.Dispose();
                        //释放Graphics
                        g.Dispose();
                        //将生成得图片读入MemoryStream
                        MemoryStream ms = new MemoryStream();
                        newBitmap.Save(ms, ImageFormat.Jpeg);
                        newBitmap.Dispose();
                        //返回新的Image对象
                        img = Image.FromStream(ms);
                        ms.Dispose();
                        imageAttributes.Dispose();
                        return img;
                    }
                    //原图足够大
                    else
                    {
                        //添加水印
                        g.DrawImage(markImg, new Rectangle(_MarkX, _MarkY, markImg.Width, markImg.Height), 0, 0, markImg.Width, markImg.Height, GraphicsUnit.Pixel, imageAttributes);
                        //释放Graphics
                        g.Dispose();
                        //将生成得图片读入MemoryStream
                        MemoryStream ms = new MemoryStream();
                        newBitmap.Save(ms, ImageFormat.Jpeg);
                        //返回新的Image对象
                        img = Image.FromStream(ms);
                        ms.Dispose();
                        return img;
                    }
                }
                return img;
            }
            catch
            {
                return img;
            }
        }
        /// <summary>
        /// 添加水印，此方法适用于gif格式得图片
        /// </summary>
        /// <param name="image">需要添加水印得图片</param>
        /// <returns>添加水印之后得图片</returns>
        private void Mark()
        {
            //this._WaterImage = Mark(this.SourceImage);
        }
        #endregion

        #region IDisposable 成员
        public void Dispose()
        {
            if (_SourceImage == null) return;
            _SourceImage.Dispose();
            _SourceImage = null;
            if (_WaterImage == null) return;
            _WaterImage.Dispose();
            _WaterImage = null;
        }

        ~Watermark()
        {
            Dispose();
        }
        #endregion
    }
}